#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN

//Must be declared so that our local glxext.h is picked up, rather than the system one
#define GLX_GLXEXT_LEGACY 

#ifdef _WIN32
#include <windows.h>
#include "GLWindow.h"
#endif

#include "Game.h"
#include "MainMenu.h"
#include "AudioManager.h"

#ifdef _WIN32
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR cmdLine,
                   int cmdShow)
{
#else
int main(int argc, char** argv)
{
#endif
    //Set our window settings
    //const int windowWidth = 768; //1024;
    //const int windowHeight = 768;
    const int windowWidth = 960; 
    const int windowHeight = 640;
    const int windowBPP = 24;
    bool windowFullscreen = false;

#ifdef _WIN32
    //This is our window
    GLWindow programWindow(hInstance);
#endif

    //The example OpenGL code
    //Game example(&programWindow)
    //MainMenu example(&programWindow);
    //Scene* currentScene = &example;
    MainMenu* example = new MainMenu(&programWindow);
    //Game* example = new Game(&programWindow);
    Scene* currentScene = example;

    //Attach our example to our window
    //programWindow.attachScene(&example);
    programWindow.attachScene(currentScene);

    //Attempt to create the window
    if (!programWindow.create(windowWidth, windowHeight, windowBPP, windowFullscreen))
    {
        //If it fails
#ifdef _WIN32
        MessageBox(NULL, "Unable to create the OpenGL Window", "An error occurred", MB_ICONERROR | MB_OK);
#endif
        programWindow.destroy(); //Reset the display and exit
        return 1;
    }

    // Initialize the audio system
    AudioManager *audioManager = AudioManager::getInstance();

    //if (!example.init()) //Initialize our example
    if (!currentScene->init())
    {
#ifdef _WIN32
        MessageBox(NULL, "Could not initialize the application", "An error occurred", MB_ICONERROR | MB_OK);
#endif
        programWindow.destroy(); //Reset the display and exit
        return 1;
    }

    //This is the mainloop, we render frames until isRunning returns false
    while(programWindow.isRunning())
    {
        programWindow.processEvents(); //Process any window events

        //We get the time that passed since the last frame
        float elapsedTime = programWindow.getElapsedSeconds();

        //example.prepare(elapsedTime); //Do any pre-rendering logic
        //example.render(); //Render the scene
        Scene *newScene = currentScene->nextScene();
        if (newScene == NULL)
        {
            break;
        }
        else if ((newScene != NULL) && (newScene != currentScene))
        {
            // Execute transition
            Dimension screenSize = currentScene->getScreenSize();
            currentScene->shutdown();
            delete currentScene;
            currentScene = newScene;
            programWindow.attachScene(currentScene);
            currentScene->init();
            currentScene->onResize(static_cast<int> (screenSize.width), 
                                   static_cast<int> (screenSize.height));
        }
        else
        {
            currentScene->prepare(elapsedTime); //Do any pre-rendering logic
            currentScene->render(); //Render the scene
        }

        programWindow.swapBuffers();
    }

    currentScene->shutdown(); //Free any resources
    delete currentScene;
    delete audioManager;
    programWindow.destroy(); //Destroy the program window

    return 0; //Return success
}
